home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1996 February
/
EnigmA AMIGA RUN 04 (1996)(G.R. Edizioni)(IT)[!][issue 1996-02][Skylink CD III].iso
/
earcd
/
dtype
/
xpkdt10b.lha
/
Src
/
dispatch.c
< prev
Wrap
C/C++ Source or Header
|
1995-11-21
|
11KB
|
340 lines
/*
** dispatch.c - dispatcher for XPK DataType class
** Copyright © 1995 Michael Letowski
*/
#include <exec/types.h>
#include <exec/memory.h>
#include <dos/dos.h>
#include <dos/dosasl.h>
#include <intuition/classes.h>
#include <datatypes/datatypesclass.h>
#include <datatypes/datatypes.h>
#include <libraries/xpk.h>
#include <utility/tagitem.h>
#include <support/types.h>
#include <support/dos.h>
#include <string.h>
#include <proto/dos.h>
#include <proto/exec.h>
#include <proto/datatypes.h>
#include <proto/intuition.h>
#include <proto/utility.h>
#include <clib/support_protos.h>
#include "classbase.h"
#include "dispatch.h"
/****** xpk.datatype/xpk.datatype *******************************************
*
* NAME
* xpk.datatype -- data type for XPK and PowerPacker compressed files.
*
* FUNCTION
* The xpk data type is used to decompress XPK and PowerPacker
* compressed files. Decompressed files are then placed in "T:" logical
* directory and passed again to DataTypes system via NewDTObject().
* DataTypes system is then free to handle them (it will usually show
* contents of a decompressed file).
*
* METHODS
* OM_NEW -- Decompress source file, place it in "T:" directory and call
* OM_NEW method on that file.
*
* OM_DISPOSE -- Delete the object and all associated temporary files.
*
* NOTES
* Since the data type just calls OM_NEW method on a decompressed file
* it will work for files which were compressed several times (eg. DLTA
* encoded and SHRI compressed).
*
* BUGS
* Will not work for AmigaGuide® compressed files (due to a bug in
* amigaguide.datatype, I suspect).
* Can not handle encrypted files.
*
* SEE ALSO
* amigaguide.datatype, xpkmaster.library, datatypes.library.
*
*****************************************************************************
*
*/
/*
** Private structures
*/
struct XPKData
{
Object *xd_Object;
STRPTR xd_Name;
}; /* XPKData */
/*
** Private prototypes
*/
STATIC ASM Object *Dispatch(R_A0 Class *cl, R_A2 Object *o, R_A1 Msg msg);
STATIC Object *NewXPK(Class *cl, Object *o, Msg msg);
STATIC Object *DisposeXPK(Class *cl, Object *o, Msg msg);
STATIC Object *DefaultXPK(Class *cl, Object *o, Msg msg);
STATIC STRPTR CreateTempFile(struct ClassBase *cb, STRPTR name);
STATIC VOID DeleteTempFile(struct ClassBase *cb, STRPTR name);
STATIC LONG XPK2DOS(struct ClassBase *cb, LONG xpkError);
/*
** DataTypes stubs
*/
STATIC ULONG LocSetDTAttrs(struct ClassBase *cb, Object *o, ULONG data, ...);
STATIC ULONG LocGetDTAttrs(struct ClassBase *cb, Object *o, ULONG data, ...);
/*
** xpk.h kludge
*/
#pragma tagcall XpkBase XpkUnpackTags 30 801
/*
** Public functions
*/
Class *InitClass(struct ClassBase *cb)
{
Class *CL;
/* Create our class (an instance of XPKData) */
if(CL=MakeClass(DATATYPENAME,SUPERCLASSNAME,NULL,sizeof(struct XPKData),0))
{
CL->cl_Dispatcher.h_Entry=(HOOKFUNC)Dispatch;
CL->cl_UserData=(ULONG)cb;
AddClass(CL);
}
return(CL);
} /* InitClass */
/*
** Level 1 private functions
*/
STATIC ASM Object *Dispatch(R_A0 Class *cl, R_A2 Object *o, R_A1 Msg msg)
{
Object *Obj;
switch(msg->MethodID)
{
case OM_NEW: Obj=NewXPK(cl,o,msg); break;
case OM_DISPOSE: Obj=DisposeXPK(cl,o,msg); break;
default: Obj=DefaultXPK(cl,o,msg); break;
}
return(Obj);
} /* Dispatch */
/*
** Level 2 private functions
*/
STATIC Object *NewXPK(Class *cl, Object *o, Msg msg)
{
STATIC CONST struct TagItem UnpackTags[]=
{
{XPK_PassThru, TRUE},
{TAG_DONE, 0}
}; /* UnpackTags */
STATIC CONST Tag FilterTags[]=
{
DTA_SourceType,DTA_DataType,DTA_Name,DTA_Handle,TAG_DONE
}; /* FilterTags */
struct ClassBase *cb=(struct ClassBase *)cl->cl_UserData;
struct TagItem *Clone,*Tag;
struct TagItem *Attrs=((struct opSet *)msg)->ops_AttrList;
Object *NewObj=NULL;
struct XPKData *XD;
STRPTR Name,RealName;
BPTR Lock,Lock2,Handle;
LONG Err,RC=0;
try(Clone=CloneTagItems(Attrs), NO_CLONE);
/* Get name and object lock */
RealName= (STRPTR)GetTagData(DTA_Name,NULL,Clone);
Lock= (BPTR)GetTagData(DTA_Handle,NULL,Clone);
try(RealName && Lock, NO_LOCK);
/* Remove unnecessary attributes */
FilterTagItems(Clone,FilterTags,TAGFILTER_NOT);
if(Name=CreateTempFile(cb,RealName)) /* Create temporary file name */
{
Err=XPKERR_IOERRIN; /* No success yet */
if(Lock2=DupLock(Lock)) /* Get duplicate of lock */
if(Handle=OpenFromLock(Lock2)) /* Open from that lock */
{ /* Could open - Lock2 is invalid */
/* Do unpacking */
Err=XpkUnpackTags(XPK_InFH, Handle,
XPK_OutName, Name,
TAG_MORE, UnpackTags);
Close(Handle); /* Close file */
}
else /* Could not open */
UnLock(Lock2); /* Unlock file */
if(Err==XPKERR_OK || Err==XPKERR_NOTPACKED) /* Error? */
/* Create new object */
if(NewObj=(Object *)DoSuperMethodA(cl,o,msg))
{
XD=INST_DATA(cl,NewObj);
if(XD->xd_Object=NewDTObjectA(Name,Clone))
{
SetAttrs(NewObj,DTA_ObjName,RealName,TAG_DONE);
XD->xd_Name=Name;
}
else /* Could not create object */
{
RC=IoErr(); /* Get DOS error code */
CoerceMethod(cl,NewObj,OM_DISPOSE); /* Destroy object (super class) */
NewObj=NULL; /* Mark this fact */
}
}
else /* Error creating object */
RC=IoErr(); /* Get DOS error code */
else /* Error unpacking */
RC=XPK2DOS(cb,Err); /* Get DOS error code */
}
else /* Error creating temp file */
RC=IoErr(); /* Get DOS error code */
unless(NewObj) /* New object not created */
DeleteTempFile(cb,Name); /* Delete temporary file */
/* Exceptions */
SetIoErr(RC); /* Set error code */
catch(NO_LOCK, );
catch(NO_CLONE, FreeTagItems(Clone));
return(NewObj);
} /* NewXPK */
STATIC Object *DisposeXPK(Class *cl, Object *o, Msg msg)
{
struct ClassBase *cb=(struct ClassBase *)cl->cl_UserData;
struct XPKData *XD=INST_DATA(cl,o);
if(XD->xd_Object) DisposeDTObject(XD->xd_Object);
if(XD->xd_Name) DeleteTempFile(cb,XD->xd_Name);
return((Object *)DoSuperMethodA(cl,o,msg));
} /* DisposeXPK */
STATIC Object *DefaultXPK(Class *cl, Object *o, Msg msg)
{
struct XPKData *XD=INST_DATA(cl,o);
return((Object *)DoMethodA(XD->xd_Object,msg));
} /* DefaultXPK */
/*
** Level 3 private functions
*/
STATIC STRPTR CreateTempFile(struct ClassBase *cb, STRPTR name)
{
STRPTR Name,RealName=FilePart(name);
ULONG Len;
BPTR DirLock;
Len=strlen(RealName)+24;
if(Name=AllocVec(Len,MEMF_PUBLIC)) /* Allocate space for name */
{ /* Space allocated */
SPrintf(Name,"T:XPKDT-%08lx-T%04ld",ThisProcessS,cb->cb_UniqueCnt++);
if(DirLock=CreateDir(Name)) /* Try to create directory */
{ /* Could create directory */
AddPart(Name,RealName,Len); /* Append file name */
UnLock(DirLock); /* Free lock */
}
else /* Dir not created */
{ /* Create unique file name */
strcat(Name,"-"); /* Append dash */
strcat(Name,RealName); /* Append file name */
}
}
return(Name);
} /* CreateTempFile */
STATIC VOID DeleteTempFile(struct ClassBase *cb, STRPTR name)
{
STRPTR Sep;
if(name) /* Name valid */
{
Sep=PathPart(name); /* Find path/file separator */
DeleteFile(name); /* Delete file */
if(Sep!=FilePart(name)) /* Dir component present */
{
*Sep='\0'; /* Null terminate string */
DeleteFile(name); /* Delete directory */
}
FreeVec(name); /* Free space */
}
} /* DeleteTempFile */
STATIC LONG XPK2DOS(struct ClassBase *cb, LONG xpkErr)
{
LONG DOSErr=ThisProcessS->pr_Result2;
unless(DOSErr) /* Error not set */
switch(xpkErr)
{
case XPKERR_NOFUNC: DOSErr=ERROR_NOT_IMPLEMENTED; break;
case XPKERR_NOFILES: DOSErr=ERROR_NOT_IMPLEMENTED; break;
case XPKERR_IOERRIN: DOSErr=ERROR_OBJECT_WRONG_TYPE; break;
case XPKERR_IOERROUT: DOSErr=ERROR_OBJECT_WRONG_TYPE; break;
case XPKERR_CHECKSUM: DOSErr=DTERROR_INVALID_DATA; break;
case XPKERR_VERSION: DOSErr=ERROR_INVALID_RESIDENT_LIBRARY; break;
case XPKERR_NOMEM: DOSErr=ERROR_NO_FREE_STORE; break;
case XPKERR_LIBINUSE: DOSErr=ERROR_INVALID_RESIDENT_LIBRARY; break;
case XPKERR_WRONGFORM: DOSErr=DTERROR_UNKNOWN_COMPRESSION; break;
case XPKERR_SMALLBUF: DOSErr=ERROR_BUFFER_OVERFLOW; break;
case XPKERR_LARGEBUF: DOSErr=ERROR_BUFFER_OVERFLOW; break;
case XPKERR_WRONGMODE: DOSErr=DTERROR_UNKNOWN_COMPRESSION; break;
case XPKERR_NEEDPASSWD: DOSErr=ERROR_OBJECT_WRONG_TYPE; break;
case XPKERR_CORRUPTPKD: DOSErr=DTERROR_INVALID_DATA; break;
case XPKERR_MISSINGLIB: DOSErr=ERROR_INVALID_RESIDENT_LIBRARY; break;
case XPKERR_BADPARAMS: DOSErr=ERROR_TOO_MANY_ARGS; break;
case XPKERR_EXPANSION: DOSErr=ERROR_BUFFER_OVERFLOW; break;
case XPKERR_NOMETHOD: DOSErr=ERROR_INVALID_RESIDENT_LIBRARY; break;
case XPKERR_ABORTED: DOSErr=ERROR_BREAK; break;
case XPKERR_TRUNCATED: DOSErr=DTERROR_NOT_ENOUGH_DATA; break;
case XPKERR_WRONGCPU: DOSErr=ERROR_INVALID_RESIDENT_LIBRARY; break;
case XPKERR_PACKED: DOSErr=ERROR_OBJECT_WRONG_TYPE; break;
case XPKERR_NOTPACKED: DOSErr=ERROR_OBJECT_WRONG_TYPE; break;
case XPKERR_FILEEXISTS: DOSErr=ERROR_OBJECT_EXISTS; break;
case XPKERR_OLDMASTLIB: DOSErr=ERROR_INVALID_RESIDENT_LIBRARY; break;
case XPKERR_OLDSUBLIB: DOSErr=ERROR_INVALID_RESIDENT_LIBRARY; break;
case XPKERR_NOCRYPT: DOSErr=ERROR_OBJECT_WRONG_TYPE; break;
case XPKERR_NOINFO: DOSErr=ERROR_INVALID_RESIDENT_LIBRARY; break;
case XPKERR_LOSSY: DOSErr=ERROR_OBJECT_WRONG_TYPE; break;
case XPKERR_NOHARDWARE: DOSErr=ERROR_NOT_IMPLEMENTED; break;
case XPKERR_BADHARDWARE: DOSErr=ERROR_NOT_IMPLEMENTED; break;
case XPKERR_WRONGPW: DOSErr=ERROR_OBJECT_WRONG_TYPE; break;
default: DOSErr=ERROR_OBJECT_WRONG_TYPE; break;
}
return(DOSErr);
} /* XPK2DOS */
/*
** DataTypes stubs
*/
STATIC ULONG LocSetDTAttrs(struct ClassBase *cb, Object *o, ULONG data, ...)
{
return(SetDTAttrsA(o,NULL,NULL,(struct TagItem *)&data));
} /* LocSetDTAttrs */
STATIC ULONG LocGetDTAttrs(struct ClassBase *cb, Object *o, ULONG data, ...)
{
return(GetDTAttrsA(o,(struct TagItem *)&data));
} /* LocGetDTAttrs */